#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
回测系统的Web路由
提供回测系统的Web界面和API
"""

import os
import json
import logging
import pandas as pd
from flask import Blueprint, render_template, request, jsonify, send_file
from src.backtesting.backtester import BackTester

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)

# 创建Blueprint
backtesting_bp = Blueprint('backtesting', __name__, url_prefix='/backtesting')

# 确保回测结果目录存在
os.makedirs('data/results/backtesting', exist_ok=True)

# 全局回测器实例
backtester = BackTester(data_path='data')
logger.info(f"回测系统初始化，数据路径: {backtester.data_path}, 结果路径: {backtester.results_path}")

@backtesting_bp.route('/')
def index():
    """回测系统主页"""
    # 获取历史回测报告
    report_dir = backtester.results_path
    reports = []
    
    if os.path.exists(report_dir):
        for file in os.listdir(report_dir):
            if file.endswith('.json') and file != 'report.json':
                report_path = os.path.join(report_dir, file)
                try:
                    with open(report_path, 'r', encoding='utf-8') as f:
                        report = json.load(f)
                        
                    # 提取报告信息
                    report_info = {
                        'file_name': file,
                        'timestamp': report.get('timestamp', '未知'),
                        'total_tests': report.get('summary', {}).get('total_tests', 0),
                        'date_range': report.get('summary', {}).get('date_range', '未知'),
                        'overall_avg_return': report.get('summary', {}).get('overall_avg_return', 0),
                        'overall_excess_return': report.get('summary', {}).get('overall_excess_return', 0),
                        'overall_win_rate': report.get('summary', {}).get('overall_win_rate', 0)
                    }
                    
                    reports.append(report_info)
                except Exception as e:
                    logger.error(f"读取报告 {file} 失败: {e}")
    
    # 按时间排序
    reports.sort(key=lambda x: x['timestamp'], reverse=True)
    
    return render_template(
        'backtesting.html',
        reports=reports
    )

@backtesting_bp.route('/run', methods=['POST'])
def run_backtest():
    """运行回测"""
    try:
        # 获取请求参数
        data = request.json or {}
        result_dir = data.get('result_dir')
        report_name = data.get('report_name', f"report_{pd.Timestamp.now().strftime('%Y%m%d_%H%M%S')}.json")
        
        # 确保报告名称以.json结尾
        if not report_name.endswith('.json'):
            report_name += '.json'
            
        # 设置报告路径
        report_path = os.path.join(backtester.results_path, report_name)
        
        # 运行回测
        logger.info(f"开始回测，结果将保存到 {report_path}")
        report = backtester.run_backtest(result_dir)
        
        # 保存报告
        with open(report_path, 'w', encoding='utf-8') as f:
            json.dump(report, f, ensure_ascii=False, indent=2)
            
        # 返回结果
        return jsonify({
            'success': True,
            'message': '回测完成',
            'report_path': report_path,
            'report_name': report_name,
            'summary': report.get('summary', {})
        })
        
    except Exception as e:
        logger.error(f"回测失败: {e}")
        return jsonify({
            'success': False,
            'message': f'回测失败: {str(e)}'
        }), 500

@backtesting_bp.route('/report/<report_name>')
def get_report(report_name):
    """获取回测报告"""
    try:
        # 构建报告路径
        report_path = os.path.join(backtester.results_path, report_name)
        
        if not os.path.exists(report_path):
            return jsonify({
                'success': False,
                'message': f'报告 {report_name} 不存在'
            }), 404
            
        # 读取报告
        with open(report_path, 'r', encoding='utf-8') as f:
            report = json.load(f)
            
        return jsonify({
            'success': True,
            'report': report
        })
        
    except Exception as e:
        logger.error(f"获取报告 {report_name} 失败: {e}")
        return jsonify({
            'success': False,
            'message': f'获取报告失败: {str(e)}'
        }), 500

@backtesting_bp.route('/performance/<report_name>')
def get_performance_image(report_name):
    """获取回测性能图表"""
    try:
        # 构建图片路径（报告名称去掉.json后缀，加上.png后缀）
        image_name = report_name.replace('.json', '.png')
        image_path = os.path.join(backtester.results_path, image_name)
        
        if not os.path.exists(image_path):
            # 如果图片不存在，尝试找报告并重新生成图片
            report_path = os.path.join(backtester.results_path, report_name)
            
            if os.path.exists(report_path):
                with open(report_path, 'r', encoding='utf-8') as f:
                    report = json.load(f)
                    
                backtester.performance_metrics = report.get('performance_metrics', {})
                backtester.visualize_performance(image_path)
            else:
                return jsonify({
                    'success': False,
                    'message': f'报告 {report_name} 不存在，无法生成性能图表'
                }), 404
                
        # 返回图片
        return send_file(image_path, mimetype='image/png')
        
    except Exception as e:
        logger.error(f"获取性能图表失败: {e}")
        return jsonify({
            'success': False,
            'message': f'获取性能图表失败: {str(e)}'
        }), 500

@backtesting_bp.route('/settings')
def settings():
    """回测设置页面"""
    # 获取回测系统默认设置
    settings = {
        'data_path': backtester.data_path,
        'price_data_path': backtester.price_data_path,
        'results_path': backtester.results_path
    }
    
    # 获取可用的分析结果目录
    result_dirs = []
    
    if os.path.exists(os.path.join(backtester.data_path, 'results')):
        for dir_name in os.listdir(os.path.join(backtester.data_path, 'results')):
            dir_path = os.path.join(backtester.data_path, 'results', dir_name)
            if os.path.isdir(dir_path):
                result_dirs.append(dir_name)
    
    return render_template(
        'backtesting_settings.html',
        settings=settings,
        result_dirs=result_dirs
    )

@backtesting_bp.route('/detail/<report_name>')
def report_detail(report_name):
    """报告详情页面"""
    try:
        # 构建报告路径
        report_path = os.path.join(backtester.results_path, report_name)
        
        if not os.path.exists(report_path):
            return render_template(
                'error.html',
                error_message=f'报告 {report_name} 不存在'
            )
            
        # 读取报告
        with open(report_path, 'r', encoding='utf-8') as f:
            report = json.load(f)
            
        # 检查图片是否存在
        image_name = report_name.replace('.json', '.png')
        image_path = os.path.join(backtester.results_path, image_name)
        has_image = os.path.exists(image_path)
        
        return render_template(
            'backtesting_detail.html',
            report_name=report_name,
            report=report,
            has_image=has_image,
            image_name=image_name
        )
        
    except Exception as e:
        logger.error(f"获取报告详情失败: {e}")
        return render_template(
            'error.html',
            error_message=f'获取报告详情失败: {str(e)}'
        )

@backtesting_bp.route('/delete/<report_name>', methods=['POST'])
def delete_report(report_name):
    """删除回测报告"""
    try:
        # 构建报告路径
        report_path = os.path.join(backtester.results_path, report_name)
        
        if not os.path.exists(report_path):
            return jsonify({
                'success': False,
                'message': f'报告 {report_name} 不存在'
            }), 404
            
        # 删除报告
        os.remove(report_path)
        
        # 检查并删除对应的图片
        image_path = report_path.replace('.json', '.png')
        if os.path.exists(image_path):
            os.remove(image_path)
            
        return jsonify({
            'success': True,
            'message': f'成功删除报告 {report_name}'
        })
        
    except Exception as e:
        logger.error(f"删除报告 {report_name} 失败: {e}")
        return jsonify({
            'success': False,
            'message': f'删除报告失败: {str(e)}'
        }), 500 